當我們使用狀態管理之後,可能會思考,是否再也不需要使用 StatefulWidget 了?今天我們就來談談這個問題。首先,我們先看一個例子,假設今天畫設計師設計了一個按鈕,當按鈕被壓著時,按鈕需要變個顏色,讓使用者感知自己有按到按鈕
https://dartpad.dev/?id=1ce393e000000b9df586a11d7c6ae495
在上面的例子中,我們使用狀態管理來實現這個設計,可以發現在 ButtonStatus 中,我們維護了一個按鈕是否被按下的布林值,並且宣告了一個相對應的 Provider。雖然我們可以用狀態管理套件,完成這個功能,但實際上,會發現其實 ButtonStatus 並沒有多大的意義,形成一個壞味道:Lazy Class。
我們來看看使用 StatefulWidget 實現會變得如何?
https://dartpad.dev/?id=4c56071a63fa7416c4c22578694fa1e0
可以發現在這個場景中,使用 StatefulWidget 實現的話,我們只要在 State 維護一個布林值,並利用 setState 更新按鈕狀態與重 build 畫面。
客端程式中,大多時候都要維護各式各樣的狀態,我們可以把狀態分為兩種:暫存狀態和程式狀態。在按鈕的例子中,isPressed 的布林值就比較屬於暫存狀態,當 Button 消失時,這 isPressed 也隨之消失。在昨天顯示 User 的例子中,即便畫面關閉了,User 這個狀態還是需要存在程式中,以便其他畫面使用。
那是否暫存狀態就得永遠使用 StatefulWidget 呢?那倒也不是,管理狀態的邏輯比較複雜時,我們適當的使用狀態管理套件,將邏輯與畫面分開,能夠將一個比較複雜的類別,簡化成兩個比較簡單的類別,是具有意義的。在前天的選擇照片的例子中,選擇的照片在離開了選擇照片頁面之後,可能也不存在意義了。但是我們還是使用了狀態管理來改善,也是基於上述理由。
反之亦然,是否所有程式狀態也並非一定要使用狀態管理。在按鈕的例子中,假設需求變得複雜了,我們需要一個時間倒數的按鈕,並且擁有倒數/暫停等較複雜的行為時,使用狀態管理還是有一定好處。
https://dartpad.dev/?id=c93d29f9a38a0482a15ba028155d681e
如何選擇使用 StatefulWidget 或者狀態管理套件,可以先判斷情境屬於暫存狀態或者程式狀態,並決定使用哪種實現,當實現一版之後,發現暫存狀態的邏輯過於複雜,還是可以改用狀態管理套件。